package com.dayuanit.chat;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;

/**
 * 大猿聊天室服务器App
 */
public class Server {

    //当前在线的所有客户端集合
    private static final List<Socket> clientList = new ArrayList<>();
    private static final Map<Socket, Thread> threadMap = new HashMap<>();

    public static void main(String[] args) throws IOException {

        //从命令行里获取端口号
        int port = 9999;
        if (args.length > 0) {
            port = Integer.parseInt(args[0]);
        }
        //创建服务器端的Socket
        //向操作系统申请端口，如果端口号已经被别的应用使用了，则报错。

        //由于要交换资源，所以需要IO流，又由于资源不在同一台机器，所以需要建立TCP/IP连接，
        //建立连接需要通过Socket进行操作。
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("server已在"+port+"端口启动...");

        //通过死循环 保证服务器端的代码7*24小时，不间断的提供服务。
        while (true) {
            System.out.println(">>>>>>>>> 循环...begin");
            //accept方法会阻塞，直到有客户端连接过来，则返回客户端的Socket对象。
            Socket clieckSocket = serverSocket.accept();//等待客户端的连接
            System.out.println("server接收一个客户端...");

            //把客户存放到集合中 待消息广播

            synchronized (Server.class) {
                clientList.add(clieckSocket);
            }

            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        //通过输入流读取客户端的信息
                        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clieckSocket.getInputStream()));
                        String msg = null;
                        //此读取客户端信息，有则读取，无则等待阻塞，所以while循环始终无法退出，到账服务端无法接收下一个客户端的连接
                        while (!Thread.currentThread().isInterrupted() && null != (msg = bufferedReader.readLine())) {
                            System.out.println("接收客户端的消息：" + msg);

                            //服务器将消息再发送给客户端
                            //要将消息广播给聊天室所有的人
                            Iterator<Socket> iterator = clientList.iterator();
                            while (iterator.hasNext()) {
                                Socket socket = iterator.next();
                                try {
                                    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                                    bufferedWriter.write(msg);
                                    bufferedWriter.newLine();
                                    bufferedWriter.flush();
                                } catch (Exception e) {
                                    System.err.println("移走已下线的客户端");

                                    synchronized (Server.class) {
                                        iterator.remove();//在遍历的时候，如果要删除元素，使用Iterator迭代器

                                        //通过当前遍历的socket，得到对应的线程，将其中断。
                                        Thread t = threadMap.get(socket);
                                        t.interrupt();//关闭掉线程
                                        threadMap.remove(socket);//将其从map中移除
                                    }

                                }
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }, "伺候客户端的店小二");

            thread.start();//启动线程

            synchronized (Server.class) {
                threadMap.put(clieckSocket, thread);
            }

            System.out.println(">>>>>>>>> 循环...end");
        }
    }
}
